(function(){
  /**
   * util-request.js - The utilities for requesting script and style files
   * ref: tests/research/load-js-css/test.html
   */
  
  function isType(type) {
    return function(obj) {
      return {}.toString.call(obj) == "[object " + type + "]"
    }
  }
  
  var isString = isType("String")
  
  var doc = document
  var head = doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement
  var baseElement = head.getElementsByTagName("base")[0]
  
  var IS_CSS_RE = /\.css(?:\?|$)/i
  var currentlyAddingScript
  var interactiveScript
  
  // `onload` event is not supported in WebKit < 535.23 and Firefox < 9.0
  // ref:
  //  - https://bugs.webkit.org/show_activity.cgi?id=38995
  //  - https://bugzilla.mozilla.org/show_bug.cgi?id=185236
  //  - https://developer.mozilla.org/en/HTML/Element/link#Stylesheet_load_events
  var isOldWebKit = +navigator.userAgent
    .replace(/.*(?:AppleWebKit|AndroidWebKit)\/?(\d+).*/i, "$1") < 536
  
  function isFunction(obj) {
    return {}.toString.call(obj) == "[object Function]"
  }
  function request(url, callback, charset, crossorigin) {
    var isCSS = IS_CSS_RE.test(url)
    var node = doc.createElement(isCSS ? "link" : "script")
  
    if (charset) {
      var cs = isFunction(charset) ? charset(url) : charset
      if (cs) {
        node.charset = cs
      }
    }
  
    if (crossorigin !== void 0) {
      node.setAttribute("crossorigin", crossorigin)
    }
  
    addOnload(node, callback, isCSS, url)
  
    if (isCSS) {
      node.rel = "stylesheet"
      node.href = url
    }
    else {
      node.async = true
      node.src = url
    }
  
    // For some cache cases in IE 6-8, the script executes IMMEDIATELY after
    // the end of the insert execution, so use `currentlyAddingScript` to
    // hold current node, for deriving url in `define` call
    currentlyAddingScript = node
  
    // ref: #185 & http://dev.jquery.com/ticket/2709
    baseElement ?
      head.insertBefore(node, baseElement) :
      head.appendChild(node)
  
    currentlyAddingScript = null
  }
  
  function addOnload(node, callback, isCSS, url) {
    var supportOnload = "onload" in node
  
    // for Old WebKit and Old Firefox
    if (isCSS && (isOldWebKit || !supportOnload)) {
      setTimeout(function() {
        pollCss(node, callback)
      }, 1) // Begin after node insertion
      return
    }
  
    if (supportOnload) {
      node.onload = onload
      node.onerror = function() {
        seajs.emit("error", { uri: url, node: node })
        onload()
      }
    }
    else {
      node.onreadystatechange = function() {
        if (/loaded|complete/.test(node.readyState)) {
          onload()
        }
      }
    }
  
    function onload() {
      // Ensure only run once and handle memory leak in IE
      node.onload = node.onerror = node.onreadystatechange = null
  
      // Remove the script to reduce memory leak
      if (!isCSS && !seajs.data.debug) {
        head.removeChild(node)
      }
  
      // Dereference the node
      node = null
  
      callback()
    }
  }
  
  function pollCss(node, callback) {
    var sheet = node.sheet
    var isLoaded
  
    // for WebKit < 536
    if (isOldWebKit) {
      if (sheet) {
        isLoaded = true
      }
    }
    // for Firefox < 9.0
    else if (sheet) {
      try {
        if (sheet.cssRules) {
          isLoaded = true
        }
      } catch (ex) {
        // The value of `ex.name` is changed from "NS_ERROR_DOM_SECURITY_ERR"
        // to "SecurityError" since Firefox 13.0. But Firefox is less than 9.0
        // in here, So it is ok to just rely on "NS_ERROR_DOM_SECURITY_ERR"
        if (ex.name === "NS_ERROR_DOM_SECURITY_ERR") {
          isLoaded = true
        }
      }
    }
  
    setTimeout(function() {
      if (isLoaded) {
        // Place callback here to give time for style rendering
        callback()
      }
      else {
        pollCss(node, callback)
      }
    }, 20)
  }
  
  
  // For Developers
  seajs.request = request
  
  
  
  /**
   * util-path.js - The utilities for operating path such as id, uri
   */
  var data = seajs.data
  
  var DIRNAME_RE = /[^?#]*\//
  
  var DOT_RE = /\/\.\//g
  var DOUBLE_DOT_RE = /\/[^/]+\/\.\.\//
  var MULTI_SLASH_RE = /([^:/])\/+\//g
  
  // Extract the directory portion of a path
  // dirname("a/b/c.js?t=123#xx/zz") ==> "a/b/"
  // ref: http://jsperf.com/regex-vs-split/2
  function dirname(path) {
    return path.match(DIRNAME_RE)[0]
  }
  
  // Canonicalize a path
  // realpath("http://test.com/a//./b/../c") ==> "http://test.com/a/c"
  function realpath(path) {
    // /a/b/./c/./d ==> /a/b/c/d
    path = path.replace(DOT_RE, "/")
  
    /*
     @author wh1100717
     a//b/c ==> a/b/c
     a///b/////c ==> a/b/c
     DOUBLE_DOT_RE matches a/b/c//../d path correctly only if replace // with / first
     */
    path = path.replace(MULTI_SLASH_RE, "$1/")
  
    // a/b/c/../../d  ==>  a/b/../d  ==>  a/d
    while (path.match(DOUBLE_DOT_RE)) {
      path = path.replace(DOUBLE_DOT_RE, "/")
    }
  
    return path
  }
  
  // Normalize an id
  // normalize("path/to/a") ==> "path/to/a.js"
  // NOTICE: substring is faster than negative slice and RegExp
  function normalize(path) {
    var last = path.length - 1
    var lastC = path.charAt(last)
  
    // If the uri ends with `#`, just return it without '#'
    if (lastC === "#") {
      return path.substring(0, last)
    }
  
    return (path.substring(last - 2) === ".js" ||
      path.indexOf("?") > 0 ||
      path.substring(last - 3) === ".css" ||
      lastC === "/") ? path : path + ".js"
  }
  
  
  var PATHS_RE = /^([^/:]+)(\/.+)$/
  var VARS_RE = /{([^{]+)}/g
  
  function parseAlias(id) {
    var alias = data.alias
    return alias && isString(alias[id]) ? alias[id] : id
  }
  
  function parsePaths(id) {
    var paths = data.paths
    var m
  
    if (paths && (m = id.match(PATHS_RE)) && isString(paths[m[1]])) {
      id = paths[m[1]] + m[2]
    }
  
    return id
  }
  
  function parseVars(id) {
    var vars = data.vars
  
    if (vars && id.indexOf("{") > -1) {
      id = id.replace(VARS_RE, function(m, key) {
        return isString(vars[key]) ? vars[key] : m
      })
    }
  
    return id
  }
  
  function parseMap(uri) {
    var map = data.map
    var ret = uri
  
    if (map) {
      for (var i = 0, len = map.length; i < len; i++) {
        var rule = map[i]
  
        ret = isFunction(rule) ?
          (rule(uri) || uri) :
          uri.replace(rule[0], rule[1])
  
        // Only apply the first matched rule
        if (ret !== uri) break
      }
    }
  
    return ret
  }
  
  
  var ABSOLUTE_RE = /^\/\/.|:\//
  var ROOT_DIR_RE = /^.*?\/\/.*?\//
  
  function addBase(id, refUri) {
    var ret
    var first = id.charAt(0)
  
    // Absolute
    if (ABSOLUTE_RE.test(id)) {
      ret = id
    }
    // Relative
    else if (first === ".") {
      ret = realpath((refUri ? dirname(refUri) : data.cwd) + id)
    }
    // Root
    else if (first === "/") {
      var m = data.cwd.match(ROOT_DIR_RE)
      ret = m ? m[0] + id.substring(1) : id
    }
    // Top-level
    else {
      ret = data.base + id
    }
  
    // Add default protocol when uri begins with "//"
    if (ret.indexOf("//") === 0) {
      ret = location.protocol + ret
    }
  
    return ret
  }
  
  function id2Uri(id, refUri) {
    if (!id) return ""
  
    id = parseAlias(id)
    id = parsePaths(id)
    id = parseVars(id)
    id = normalize(id)
  
    var uri = addBase(id, refUri)
    uri = parseMap(uri)
  
    return uri
  }
  
  
  var doc = document
  var cwd = (!location.href || location.href.indexOf('about:') === 0) ? '' : dirname(location.href)
  var scripts = doc.scripts
  
  // Recommend to add `seajsnode` id for the `sea.js` script element
  var loaderScript = doc.getElementById("seajsnode") ||
    scripts[scripts.length - 1]
  
  // When `sea.js` is inline, set loaderDir to current working directory
  var loaderDir = dirname(getScriptAbsoluteSrc(loaderScript) || cwd)
  
  function getScriptAbsoluteSrc(node) {
    return node.hasAttribute ? // non-IE6/7
      node.src :
      // see http://msdn.microsoft.com/en-us/library/ms536429(VS.85).aspx
      node.getAttribute("src", 4)
  }
  
  
  // For Developers
  seajs.resolve = id2Uri
  
  
  define("seajs/seajs-css/1.0.5/seajs-css-debug", [], {});
  })();